package cn.itcast.nems.journal.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import cn.itcast.ic.msplatform.api.model.Dictionary;
import cn.itcast.nems.base.dto.DictionaryDTO;
import cn.itcast.nems.base.service.DictionaryService;
import cn.itcast.nems.journal.dto.AllJournalTransferReasonVDTO;
import cn.itcast.nems.journal.dto.JournalTransferReasonVDTO;
import cn.itcast.nems.journal.service.JournalTransferReasonServiceV2;
import cn.itcast.nems.studentrecord.dao.entity.JournalTransferType;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class JournalTransferReasonServiceV2Impl implements JournalTransferReasonServiceV2 {

    private final DictionaryService dictionaryService;

    private final static Map<String, JournalTransferType> typeMap = new HashMap<>();

    static {
        typeMap.put("NEMS_JOURNAL_TRANSFER_REASON", JournalTransferType.TRANSFER);
        typeMap.put("NEMS_JOURNAL_DELAY_REASON", JournalTransferType.DELAY);
        typeMap.put("NEMS_JOURNAL_EXCHANGE_REASON", JournalTransferType.EXCHANGE);
        typeMap.put("NEMS_JOURNAL_SUSPENSION_REASON", JournalTransferType.SUSPENSION);
    }

    @Override
    public JournalTransferReasonVDTO findReasonByCode(String reasonCode) {
        Assert.hasText(reasonCode, "转班原因code不能为空");
        var rawList = dictionaryService.list(new DictionaryDTO(reasonCode));
        Assert.isTrue(rawList != null && !rawList.isEmpty(), "未找到对应的转班原因");
        return map(rawList.get(0));
    }

    @Override
    public JournalTransferReasonVDTO findReasonByCodeOrNull(String reasonCode) {
        if (!StringUtils.hasText(reasonCode)) {
            return null;
        }
        return findReasonByCode(reasonCode);
    }

    // todo 将不需要all的地方优化一下能提高效率
    @Override
    public AllJournalTransferReasonVDTO all() {
        final Map<JournalTransferType, Map<String, JournalTransferReasonVDTO>> allMap = new HashMap<>();
        typeMap.forEach((key, value) -> {
            var map = dictionaryService.list(new DictionaryDTO(key))
                    .stream()
                    .flatMap(this::childrenStream)
                    .filter(Objects::nonNull)
                    .map(this::map)
                    .collect(Collectors.toMap(JournalTransferReasonVDTO::getCode, v -> v));
            allMap.put(value, map);
        });
        return new AllJournalTransferReasonVDTO(allMap);
    }

    @Override
    public AllJournalTransferReasonVDTO allByName() {
        final Map<JournalTransferType, Map<String, JournalTransferReasonVDTO>> allMap = new HashMap<>();
        typeMap.forEach((key, value) -> {
            var map = dictionaryService.list(new DictionaryDTO(key))
                    .stream()
                    .flatMap(this::childrenStream)
                    .filter(Objects::nonNull)
                    .map(this::map)
                    .collect(Collectors.toMap(JournalTransferReasonVDTO::getName, v -> v));
            allMap.put(value, map);
        });
        return new AllJournalTransferReasonVDTO(allMap);
    }
    
    private Dictionary first(List<Dictionary> dicList) {
        if (dicList == null || dicList.isEmpty()) {
            return null;
        }
        return dicList.get(0);
    }

    private Stream<Dictionary> childrenStream(Dictionary dic) {
        if (dic == null) {
            return Stream.empty();
        }
        if (dic.getChildren() == null || dic.getChildren().isEmpty()) {
            return Stream.empty();
        }
        return dic.getChildren().stream();
    }

    private JournalTransferReasonVDTO map(Dictionary raw) {
        return new JournalTransferReasonVDTO(
                raw.getId(),
                raw.getCode(),
                raw.getName(),
                raw.getParentCode()
        );
    }
}
